// META: title=test WebNN API element-wise reciprocal operation
// META: global=window,dedicatedworker
// META: variant=?cpu
// META: variant=?gpu
// META: variant=?npu
// META: script=../resources/utils.js
// META: timeout=long

'use strict';

// https://www.w3.org/TR/webnn/#api-mlgraphbuilder-unary
// Compute the reciprocal of the input tensor, element-wise.
//
// MLOperand reciprocal(MLOperand input);


const getReciprocalPrecisionTolerance = (graphResources) => {
  const toleranceValueDict = {float32: 2, float16: 2};
  const expectedDataType =
      getExpectedDataTypeOfSingleOutput(graphResources.expectedOutputs);
  return {metricType: 'ULP', value: toleranceValueDict[expectedDataType]};
};

const reciprocalTests = [
  {
    'name': 'reciprocal float32 0D scalar',
    'graph': {
      'inputs': {
        'reciprocalInput': {
          'data': [-9.36349105834961],
          'descriptor': {'dimensions': [], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'reciprocal',
        'arguments': [{'input': 'reciprocalInput'}],
        'outputs': 'reciprocalOutput'
      }],
      'expectedOutputs': {
        'reciprocalOutput': {
          'data': [-0.10679777711629868],
          'descriptor': {'dimensions': [], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'reciprocal float32 1D constant tensor',
    'graph': {
      'inputs': {
        'reciprocalInput': {
          'data': [
            -1.0110862255096436, 4.6215386390686035,  2.417376756668091,
            -8.934871673583984,  -3.3485584259033203, -8.803302764892578,
            8.826321601867676,   6.572828769683838,   6.639494895935059,
            2.6842703819274902,  -4.627160549163818,  -6.873653411865234,
            -1.1854121685028076, 0.9572811722755432,  0.02132055163383484,
            0.35645851492881775, 4.827780246734619,   1.3128081560134888,
            8.246277809143066,   -0.2039169818162918, -9.039937019348145,
            9.942809104919434,   -9.540112495422363,  -0.08022662252187729
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'},
          'constant': true
        }
      },
      'operators': [{
        'name': 'reciprocal',
        'arguments': [{'input': 'reciprocalInput'}],
        'outputs': 'reciprocalOutput'
      }],
      'expectedOutputs': {
        'reciprocalOutput': {
          'data': [
            -0.9890353083610535, 0.21637815237045288,  0.4136715531349182,
            -0.111921027302742,  -0.29863595962524414, -0.11359372735023499,
            0.1132974773645401,  0.1521414965391159,   0.15061387419700623,
            0.3725407123565674,  -0.21611526608467102, -0.14548304677009583,
            -0.8435884118080139, 1.044625163078308,    46.90310287475586,
            2.805375576019287,   0.20713452994823456,  0.761725902557373,
            0.12126683443784714, -4.903956413269043,   -0.11062023788690567,
            0.10057520121335983, -0.10482056438922882, -12.464690208435059
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'reciprocal float32 1D tensor',
    'graph': {
      'inputs': {
        'reciprocalInput': {
          'data': [
            -1.0110862255096436, 4.6215386390686035,  2.417376756668091,
            -8.934871673583984,  -3.3485584259033203, -8.803302764892578,
            8.826321601867676,   6.572828769683838,   6.639494895935059,
            2.6842703819274902,  -4.627160549163818,  -6.873653411865234,
            -1.1854121685028076, 0.9572811722755432,  0.02132055163383484,
            0.35645851492881775, 4.827780246734619,   1.3128081560134888,
            8.246277809143066,   -0.2039169818162918, -9.039937019348145,
            9.942809104919434,   -9.540112495422363,  -0.08022662252187729
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'reciprocal',
        'arguments': [{'input': 'reciprocalInput'}],
        'outputs': 'reciprocalOutput'
      }],
      'expectedOutputs': {
        'reciprocalOutput': {
          'data': [
            -0.9890353083610535, 0.21637815237045288,  0.4136715531349182,
            -0.111921027302742,  -0.29863595962524414, -0.11359372735023499,
            0.1132974773645401,  0.1521414965391159,   0.15061387419700623,
            0.3725407123565674,  -0.21611526608467102, -0.14548304677009583,
            -0.8435884118080139, 1.044625163078308,    46.90310287475586,
            2.805375576019287,   0.20713452994823456,  0.761725902557373,
            0.12126683443784714, -4.903956413269043,   -0.11062023788690567,
            0.10057520121335983, -0.10482056438922882, -12.464690208435059
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'reciprocal float32 2D tensor',
    'graph': {
      'inputs': {
        'reciprocalInput': {
          'data': [
            -1.0110862255096436, 4.6215386390686035,  2.417376756668091,
            -8.934871673583984,  -3.3485584259033203, -8.803302764892578,
            8.826321601867676,   6.572828769683838,   6.639494895935059,
            2.6842703819274902,  -4.627160549163818,  -6.873653411865234,
            -1.1854121685028076, 0.9572811722755432,  0.02132055163383484,
            0.35645851492881775, 4.827780246734619,   1.3128081560134888,
            8.246277809143066,   -0.2039169818162918, -9.039937019348145,
            9.942809104919434,   -9.540112495422363,  -0.08022662252187729
          ],
          'descriptor': {'dimensions': [4, 6], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'reciprocal',
        'arguments': [{'input': 'reciprocalInput'}],
        'outputs': 'reciprocalOutput'
      }],
      'expectedOutputs': {
        'reciprocalOutput': {
          'data': [
            -0.9890353083610535, 0.21637815237045288,  0.4136715531349182,
            -0.111921027302742,  -0.29863595962524414, -0.11359372735023499,
            0.1132974773645401,  0.1521414965391159,   0.15061387419700623,
            0.3725407123565674,  -0.21611526608467102, -0.14548304677009583,
            -0.8435884118080139, 1.044625163078308,    46.90310287475586,
            2.805375576019287,   0.20713452994823456,  0.761725902557373,
            0.12126683443784714, -4.903956413269043,   -0.11062023788690567,
            0.10057520121335983, -0.10482056438922882, -12.464690208435059
          ],
          'descriptor': {'dimensions': [4, 6], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'reciprocal float32 3D tensor',
    'graph': {
      'inputs': {
        'reciprocalInput': {
          'data': [
            -1.0110862255096436, 4.6215386390686035,  2.417376756668091,
            -8.934871673583984,  -3.3485584259033203, -8.803302764892578,
            8.826321601867676,   6.572828769683838,   6.639494895935059,
            2.6842703819274902,  -4.627160549163818,  -6.873653411865234,
            -1.1854121685028076, 0.9572811722755432,  0.02132055163383484,
            0.35645851492881775, 4.827780246734619,   1.3128081560134888,
            8.246277809143066,   -0.2039169818162918, -9.039937019348145,
            9.942809104919434,   -9.540112495422363,  -0.08022662252187729
          ],
          'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'reciprocal',
        'arguments': [{'input': 'reciprocalInput'}],
        'outputs': 'reciprocalOutput'
      }],
      'expectedOutputs': {
        'reciprocalOutput': {
          'data': [
            -0.9890353083610535, 0.21637815237045288,  0.4136715531349182,
            -0.111921027302742,  -0.29863595962524414, -0.11359372735023499,
            0.1132974773645401,  0.1521414965391159,   0.15061387419700623,
            0.3725407123565674,  -0.21611526608467102, -0.14548304677009583,
            -0.8435884118080139, 1.044625163078308,    46.90310287475586,
            2.805375576019287,   0.20713452994823456,  0.761725902557373,
            0.12126683443784714, -4.903956413269043,   -0.11062023788690567,
            0.10057520121335983, -0.10482056438922882, -12.464690208435059
          ],
          'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'reciprocal float32 4D tensor',
    'graph': {
      'inputs': {
        'reciprocalInput': {
          'data': [
            -1.0110862255096436, 4.6215386390686035,  2.417376756668091,
            -8.934871673583984,  -3.3485584259033203, -8.803302764892578,
            8.826321601867676,   6.572828769683838,   6.639494895935059,
            2.6842703819274902,  -4.627160549163818,  -6.873653411865234,
            -1.1854121685028076, 0.9572811722755432,  0.02132055163383484,
            0.35645851492881775, 4.827780246734619,   1.3128081560134888,
            8.246277809143066,   -0.2039169818162918, -9.039937019348145,
            9.942809104919434,   -9.540112495422363,  -0.08022662252187729
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'reciprocal',
        'arguments': [{'input': 'reciprocalInput'}],
        'outputs': 'reciprocalOutput'
      }],
      'expectedOutputs': {
        'reciprocalOutput': {
          'data': [
            -0.9890353083610535, 0.21637815237045288,  0.4136715531349182,
            -0.111921027302742,  -0.29863595962524414, -0.11359372735023499,
            0.1132974773645401,  0.1521414965391159,   0.15061387419700623,
            0.3725407123565674,  -0.21611526608467102, -0.14548304677009583,
            -0.8435884118080139, 1.044625163078308,    46.90310287475586,
            2.805375576019287,   0.20713452994823456,  0.761725902557373,
            0.12126683443784714, -4.903956413269043,   -0.11062023788690567,
            0.10057520121335983, -0.10482056438922882, -12.464690208435059
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'reciprocal float32 5D tensor',
    'graph': {
      'inputs': {
        'reciprocalInput': {
          'data': [
            -1.0110862255096436, 4.6215386390686035,  2.417376756668091,
            -8.934871673583984,  -3.3485584259033203, -8.803302764892578,
            8.826321601867676,   6.572828769683838,   6.639494895935059,
            2.6842703819274902,  -4.627160549163818,  -6.873653411865234,
            -1.1854121685028076, 0.9572811722755432,  0.02132055163383484,
            0.35645851492881775, 4.827780246734619,   1.3128081560134888,
            8.246277809143066,   -0.2039169818162918, -9.039937019348145,
            9.942809104919434,   -9.540112495422363,  -0.08022662252187729
          ],
          'descriptor': {'dimensions': [2, 1, 4, 1, 3], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'reciprocal',
        'arguments': [{'input': 'reciprocalInput'}],
        'outputs': 'reciprocalOutput'
      }],
      'expectedOutputs': {
        'reciprocalOutput': {
          'data': [
            -0.9890353083610535, 0.21637815237045288,  0.4136715531349182,
            -0.111921027302742,  -0.29863595962524414, -0.11359372735023499,
            0.1132974773645401,  0.1521414965391159,   0.15061387419700623,
            0.3725407123565674,  -0.21611526608467102, -0.14548304677009583,
            -0.8435884118080139, 1.044625163078308,    46.90310287475586,
            2.805375576019287,   0.20713452994823456,  0.761725902557373,
            0.12126683443784714, -4.903956413269043,   -0.11062023788690567,
            0.10057520121335983, -0.10482056438922882, -12.464690208435059
          ],
          'descriptor': {'dimensions': [2, 1, 4, 1, 3], 'dataType': 'float32'}
        }
      }
    }
  }
];

if (navigator.ml) {
  reciprocalTests.forEach((test) => {
    webnn_conformance_test(
        buildGraphAndCompute, getReciprocalPrecisionTolerance, test);
  });
} else {
  test(() => assert_implements(navigator.ml, 'missing navigator.ml'));
}
